/**
 * WASM 加载器类
 */
export class WasmLoader<T = any> {
  private wasmPath: string;
  private exports: T | null = null;
  private loading: Promise<T> | null = null;

  constructor(wasmPath: string) {
    this.wasmPath = wasmPath;
  }

  /**
   * 加载 WASM 模块（带缓存）
   */
  async load(): Promise<T> {
    // 如果已加载，直接返回
    if (this.exports) {
      return this.exports;
    }

    // 如果正在加载，等待加载完成
    if (this.loading) {
      return this.loading;
    }

    // 开始加载
    this.loading = this.loadModule();
    this.exports = await this.loading;
    return this.exports;
  }

  /**
   * 实际加载逻辑
   */
  private async loadModule(): Promise<T> {
    try {
      if (typeof WXWebAssembly !== "undefined") {
        // 微信小程序环境
        const { instance } = await WXWebAssembly.instantiate(this.wasmPath);
        return instance.exports as T;
      } else {
        // Web 浏览器环境
        const response = await fetch(this.wasmPath);
        if (!response.ok) {
          throw new Error(`Failed to fetch WASM: ${response.statusText}`);
        }
        const buffer = await response.arrayBuffer();
        const { instance } = await WebAssembly.instantiate(buffer);
        return instance.exports as T;
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      throw new Error(`Failed to load WASM from ${this.wasmPath}: ${errorMessage}`);
    }
  }

  /**
   * 获取导出的函数（自动加载）
   */
  async getExports(): Promise<T> {
    return this.load();
  }

  /**
   * 调用 WASM 函数的便捷方法
   */
  async call<R>(funcName: keyof T, ...args: any[]): Promise<R> {
    const exports = await this.load();
    const func = exports[funcName];
    if (typeof func !== "function") {
      throw new Error(`Function ${String(funcName)} not found in WASM module`);
    }
    return (func as any)(...args);
  }
}

/**
 * 工厂函数：创建 WASM 加载器
 */
export function createWasmLoader<T = any>(wasmPath: string): WasmLoader<T> {
  return new WasmLoader<T>(wasmPath);
}

/**
 * 简单的 WASM 加载函数（直接返回 exports）
 * @param wasmPath WASM 文件路径
 * @returns 导出的函数对象
 */
export async function loadWasm<T = any>(wasmPath: string): Promise<T> {
  const loader = new WasmLoader<T>(wasmPath);
  return loader.load();
}
